一、声明提前
1、变量声明提前——变量提升
可参照这里的描述:#hello,JS:01数据类型、运算符、运算符优先级1
2
3
4//先输出a,再声明
var a=3
console.log(a) //undefined
var a=3
再如:1
2
3console.log(a)//undefined
console.log(b) //报错
var a=3
为什么console.log(a)
输出undefined
,而console.log(b)
则会报错呢?
出现这样的情况是为什么?实际上JS引擎在一行行执行代码的时候,有一些默认的运行我们并不知道,即:1
2
3var a //undefined,变量a已经前置声明,则结果为undefined console.log(a) //undefined
console.log(b) //报错,没有变量b,引用失败
a=3
最后是:变量的声明前置的完整运行:1
2
3
4
5var a //undefined,已经前置声明为undefined
console.log(a) //undefined
a=3
console.log(a)
--> undefined 3
2、函数的声明前置
先看这段代码:1
2
3
4sum(5,3) //放在任何的地方,但是只是一个函数值,并没有打印这个函数出来
function sum(a,b){
return a+b
}
设置两种看两种执行结果:
看代码,不是没有任何的变量声明?为什么就可以使用函数输出结果?这是因为函数所执行的JS引擎默认操作与变量声明前置机制是类似。相当于:包含变量数据的function函数前置,即以上代码等同于1
2
3
4
5function sum(a,b){
return a+b
}
sum(5,3)
//直接返回8
3、函数表达式的声明前置
还是先看代码:1
2
3
4
5fn()
var fn = function(){
console.log('fn...')
}
//报错,直接说fn不是一个函数
这里,function函数是一个变量,相当于把一个数字赋值给fn
,而这个function函数表达式,事实上也是有一个声明前置的,即:1
2
3
4
5var fn //undefined
fn() //此为函数,会执行,但是如果是undefined(),这种是不成立,即报错
fn = function(){
console.log('fn...')
}
那么原始代码是怎么执行的?
原始代码:1
2
3
4
5
6
7
8fn()
sum(3,4)
var fn = function(){
console.log('fn...')
}
function sum(a,b){
return a+b
}
对于浏览器来说它做了什么:一个声明前置:包括变量声明前置和函数声明前置1
2
3
4
5
6
7
8var fn //变量声明前置
function sum(a,b){
return a+b } //函数声明前置
fn()
sum(3,4)
fn = function(){
console.log('fn...')
}
二、立刻执行的函数表达式
注:关于js的语法规则如何体现?
1、先看下面这个代码
1 | (function(){ console.log('wangxiaoqin') })() |
先暂且不管它的结果如何产生。先了解一下JS的语法规则
按照这样写,为何只有function(){}
单独作为一个变量时,通过模仿语句a( );
,function(){}();
这个语句则会操作会报错,这是为什么?
对于JS引擎来说不认为是一个表达式,很像一个函数声明,再加一个括号,即会报错。那么如何让这个语句正常赋值?直接将整个函数声明加一个括号,即:1
(function(){})()
由于作为运算符,括号和括号里的内容组合为一个表达式。加上括号之后,会让JS引擎认为它是一个表达式(或引用类型),那么就符合了JS的语法规则。
总结:
当在一个函数声明后加了圆括号(也是一种运算符)后运行的话,会报错。因为这被认为是语法错误。在JS中,以function开头会被认为是语句,而语句不应该以圆括号结尾。所以此时可以选用的解决办法是把整个语句用圆括号包起来。
2、那么刚才列举的代码:
1 | (function(){ |
这类型的函数表达式有什么用?这里涉及了函数中所对应的作用域的概念,假设我们在这类函数里添加一个变量1
2
3
4
5
6 (function(){
var a =3 console.log('wangxiaoqin')
})()
console.log(a)
//运行,后台报错,a是没有被定义的。
//因为a变量是不被看到的,因为a在function函数的这个作用域里,与外界无关
3、立刻执行函数的好处:
1 | var fn=function(){} |
相当于1
fn()===(函数表达式)()
1 |
|
var fn = 3;
function fn(){
}
console.log(fn);
// 31
相当于
var fn function fn(){} //覆盖上面的 fn = 3 //重新赋值 console.log(fn) //为函数1
当函数执行有命名冲突的时候,可以认为在还是内部一开始有隐藏的声明变量这个操作
function fn(fn){
console.log(fn);
var fn = 3;
console.log(fn);
}
fn(10) //10 3
//等同于有一个默认的var fn = arguments[0]的操作
function fn(){
var fn = arguments[0] //1、将它先声明前置,再赋值,再输出
console.log(fn);
var fn = 3; //2、再赋值
console.log(fn);
} fn(10)
//10 3`